package ubadb.core.components.bufferManager.bufferPool.replacementStrategies.touchCount;

import java.util.Collection;

import ubadb.core.common.Page;
import ubadb.core.components.bufferManager.bufferPool.BufferFrame;
import ubadb.core.components.bufferManager.bufferPool.replacementStrategies.PageReplacementStrategy;
import ubadb.core.exceptions.PageReplacementStrategyException;

public class TouchCount implements PageReplacementStrategy{

	private int countIntervalSeconds = 3;
	private int agingHotCriteria = 2;

	public TouchCount(){}
	
	public TouchCount(int countIntervalSeconds, int agingHotCriteria){
		this.countIntervalSeconds = countIntervalSeconds;
		this.agingHotCriteria = agingHotCriteria;
	}
	/*Esto tiene pinta de que esta mal en caso de que todas tengan suficiente touchcount tienen que pasar todas a HOT
	 y despues sacar la primera de las hot antes de la operacion*/
	public BufferFrame findVictim(Collection<BufferFrame> bufferFrames)	throws PageReplacementStrategyException {
		TCBufferFrame victim = null;

		for (BufferFrame bufferFrame : bufferFrames) {
			TCBufferFrame TCBufferFrame = (TCBufferFrame) bufferFrame;
			if (TCBufferFrame.canBeReplaced() && TCBufferFrame.getTouchCount() < agingHotCriteria) {
				victim = TCBufferFrame;
				break;
			}
		}

		/*
		 * Si todos tienen touchCount > agingHotCriteria esto da nulo, uno tiene que sacar
		 */
		if(victim==null)
		{
			/*
			 * Busco el de menor touchCount y fecha de referencia
			 */
			TCBufferFrame lruWithMinTouchCount = null;
			
			for (BufferFrame bufferFrame : bufferFrames) {
				TCBufferFrame TCBufferFrame = (TCBufferFrame) bufferFrame;

				boolean frameCanBeReplaced = TCBufferFrame.canBeReplaced();
				if(lruWithMinTouchCount == null && frameCanBeReplaced)
					lruWithMinTouchCount = TCBufferFrame;
				else
				{
					boolean hasLessTouchCount = TCBufferFrame.getTouchCount() < lruWithMinTouchCount.getTouchCount();
					boolean hasEqualTouchCount = TCBufferFrame.getTouchCount() == lruWithMinTouchCount.getTouchCount();
					boolean hasLessReferenceDate = TCBufferFrame.getPDate().before(lruWithMinTouchCount.getPDate());
					if (frameCanBeReplaced && (hasLessTouchCount ||(hasEqualTouchCount && hasLessReferenceDate))) {
						lruWithMinTouchCount = TCBufferFrame;
					}
				}
			}
			
			victim = lruWithMinTouchCount;
		}
		
		if(victim == null)
			throw new PageReplacementStrategyException("No page can be removed from pool");
		
		return victim;
	}


	
	public BufferFrame createNewFrame(Page page) {
		return new TCBufferFrame(page, countIntervalSeconds);
	}
}